/*
* Copyright (c) 2009 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.rdfbean.maven;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.jboss.util.file.ArchiveBrowser;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.mysema.rdfbean.annotations.ClassMapping;
import com.mysema.rdfbean.model.Format;
import com.mysema.rdfbean.object.DefaultConfiguration;
import com.mysema.rdfbean.schema.SchemaGen;
/**
* SchemaGenMojo provides a Maven plugin for Sesame based schema generation
*
* @author tiwe
* @version $Id$
*
* @goal schemagen
* @phase process-classes
* @requiresDependencyResolution compile
*/
public class SchemaGenMojo extends AbstractMojo {
private static final Comparator<Class<?>> fileComparator = new Comparator<Class<?>>() {
public int compare(Class<?> o1, Class<?> o2) {
return o1.getName().compareTo(o2.getName());
}
};
/**
* @parameter
*/
private String classes;
/**
* @parameter
*/
private File classListFile;
/**
* @parameter required=true
*/
private String namespace;
/**
* @parameter
*/
private String ontology;
/**
* @parameter required=true
*/
private String prefix;
/**
* @parameter expression="${project}" readonly=true required=true
*/
private MavenProject project;
/**
* @parameter
*/
private File schemaFile;
/**
* @parameter
*/
private boolean useTurtle;
public void execute() throws MojoExecutionException, MojoFailureException {
try {
URLClassLoader classLoader = getProjectClassLoader();
final Pattern pattern = Pattern.compile(".*" + toRegex(classes) + "\\.class");
ArchiveBrowser.Filter filter = new ArchiveBrowser.Filter() {
public boolean accept(String name) {
return pattern.matcher(name).matches();
}
};
List<Class<?>> entityClasses = getEntityClasses(classLoader, filter);
Collections.sort(entityClasses, fileComparator);
DefaultConfiguration configuration = new DefaultConfiguration();
configuration.addClasses(entityClasses.toArray(new Class[entityClasses.size()]));
if (ontology == null) {
if (namespace.endsWith("#") || namespace.endsWith("/")) {
ontology = namespace.substring(0, namespace.length() - 1);
} else {
ontology = namespace;
}
}
if (schemaFile != null) {
if (!schemaFile.getParentFile().exists()) {
if (!schemaFile.getParentFile().mkdirs()) {
getLog().info("Creation of " + schemaFile.getParentFile().getPath() + " failed");
}
}
OutputStream out = new FileOutputStream(schemaFile);
SchemaGen schemaGen = new SchemaGen()
.setNamespace(prefix, namespace)
.setOntology(ontology)
.addExportNamespace(namespace)
.setConfiguration(configuration);
if (useTurtle) {
schemaGen.export(Format.TURTLE, out);
} else {
schemaGen.export(Format.RDFXML, out);
}
}
if (classListFile != null) {
StringBuilder builder = new StringBuilder();
for (Class<?> clazz : entityClasses) {
if (builder.length() > 0) {
builder.append("\n");
}
builder.append(clazz.getName());
}
// FileUtils.writeStringToFile(classListFile,
// builder.toString(), "UTF-8");
Files.write(builder.toString(), classListFile, Charsets.UTF_8);
}
} catch (IOException e) {
throw new MojoExecutionException(e.getMessage(), e);
} catch (DependencyResolutionRequiredException e) {
throw new MojoExecutionException(e.getMessage(), e);
} catch (ClassNotFoundException e) {
throw new MojoExecutionException(e.getMessage(), e);
}
}
private List<Class<?>> getEntityClasses(URLClassLoader classLoader, ArchiveBrowser.Filter filter) throws IOException,
ClassNotFoundException {
List<Class<?>> entityClasses = new ArrayList<Class<?>>();
for (URL url : classLoader.getURLs()) {
Iterator<?> classContents = ArchiveBrowser.getBrowser(url, filter);
while (classContents.hasNext()) {
ClassFile classFile = null;
DataInputStream in = null;
try {
in = new DataInputStream((InputStream) classContents.next());
classFile = new ClassFile(in);
} finally {
if (in != null) {
in.close();
}
}
AnnotationsAttribute annotations = (AnnotationsAttribute)
classFile.getAttribute(AnnotationsAttribute.visibleTag);
if (annotations != null && annotations.getAnnotation(ClassMapping.class.getName()) != null) {
Class<?> clazz = Class.forName(classFile.getName(), true, classLoader);
entityClasses.add(clazz);
}
}
}
return entityClasses;
}
@SuppressWarnings("unchecked")
protected URLClassLoader getProjectClassLoader() throws DependencyResolutionRequiredException, MalformedURLException {
List<String> classpathElements = project.getCompileClasspathElements();
List<URL> urls = new ArrayList<URL>(classpathElements.size());
for (String element : classpathElements) {
File file = new File(element);
if (file.exists()) {
urls.add(file.toURI().toURL());
}
}
return new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader());
}
private String toRegex(String classes) {
if (classes != null) {
return classes.replace("**", ".*").replace("*", "\\w+");
} else {
return "";
}
}
}